#pragma once
#include "base/function.hpp"
#include "base/noncopyable.h"
#include "base/timeeverymap.h"
#include "base/timeeventset.h"
#include "net/buffer.h"

#include <netinet/in.h>

#include <map>
#include <string>

namespace net_tools{
class Eventloop;
class Tcpclient;
class Tcpserver;
namespace base{
class Base_buffer;
class Channel;
class Timeevent;
class Timeevery;
class Threadpool;
} // namespace base
namespace net{
class Buffer_reader;
class Heartbeat;
namespace detail{
struct min_heartbeat_struct;
class heartbeat_struct;
} // namespace detail
class Connect : net_tools::base::noncopyable
{
friend class Heartbeat;
friend class Connectpool;
friend class Buffer;
friend class net_tools::Tcpclient;
friend class net_tools::Tcpserver;
 public:
  Connect(Eventloop* eventloop);
  ~Connect();
  // 向日志输出ip及端口
  void Print_ip_port(const char* status);

  // 返回读到的长度 memcpy
  unsigned int Read(void* buf,unsigned int max_size);
  // read only
  Buffer_reader* Read();

  // 写入 返回true写入成功 返回false 连接已被对方close 且已经执行完注册的close回调函数 不能再对网络库进行操作
  bool Write(void* buf,unsigned int len);
  // 返回分包的包头长
  uint32_t Peak();
  // 关闭连接
  void Close();
  // 立即关闭连接 不管还有没有数据没有发送
  void Close_right_now();
  // 添加异步功能
  void Add_task(func task);

  void Send();

  void Append(void* buf,uint32_t len);


  //该connect可读 被关闭
  void Set_read_callback(connect_func cb);
  void Set_close_callback(connect_func cb);
  void Set_lose_heartbeat_callback(connect_func cb);

  net_tools::base::Timeevent* Add_once_time_job_after(func func_,timeval begin_time);
  net_tools::base::Timeevent* Add_once_time_job_at(func func_,timeval begin_time);
  bool Del_once_time_job(net_tools::base::Timeevent* timeevent);
  bool Add_every_time_job(func func_,timeval begin_time,timeval time,int count,const std::string job_name);
  bool Del_every_time_job(const std::string job_name);
  void Add_timejob_after_sec(const std::string job_name,func todo,long int begin_after,long int sec,int count);
  timeval Get_connect_time(){return connect_time_;};

  std::string* Get_Thread_name();
  void* User_data_ptr;

 private:
  // 删除了这个在IO循环中的痕迹 FD也被关闭 缓冲区还没有
  void Clean_connect();
  void Init_channel(net_tools::base::Channel* channel);
  void Set_address(struct sockaddr_in connect_addr);
  //when client close connect,todo
  void Heartbeat_Close_connect_todo();
  void Heartbeat_lose_todo();
  void Rec_heartbeat();
  void Send_heartbeat();

  void Read_callback();
  void Close_callback();
  void Lose_heartbeat_callback();
  void User_want_close_callback();

  static net_tools::base::Threadpool* threadpool_;
  Buffer                              buffer_;
  net_tools::base::Timeeventset       once_time_job_set_;
  net_tools::base::Timeeverymap       every_time_job_map_;
  timeval                             connect_time_;
  timeval                             last_time_send_message_;
  struct sockaddr_in                  connect_addr_;
  std::string                         connect_addr_string_;
  net_tools::base::Channel*           channel_;
  net_tools::Eventloop*               eventloop_;

  Heartbeat*                    heartbeat_;
  detail::min_heartbeat_struct* min_heartbeat_struct_;
  detail::heartbeat_struct*     heartbeat_struct_;
  uint8_t                       min_heartbeat_index_;
  bool                          Is_add_heartbeat_;
  bool                          Is_send_heartbeat_;

  connect_func read_callback_;
  connect_func close_callback_;
  connect_func lose_heartbeat_callback_;
};

} // namespace net
} // namespace net_tools